#pragma once
#include "crypto/algorithms/ialgorithm/FAQIncrementalAlgorithm.h"
#include "crypto/algorithms/ialgorithm/FAQBlockAlgorithm.h"
#include "util/MemoryFIFOBuffer.hpp"

namespace yzrilyzr_crypto{
	ECLASS(FAQBaseBlockProcessAlgorithm, public FAQIncrementalAlgorithm, public FAQBlockAlgorithm){
	protected:
	yzrilyzr_util::MemoryFIFOBuffer<int8_t> buffer;
	public:
	yzrilyzr_array::ByteArray doFinal(const yzrilyzr_array::ByteArray & input){
		update(input);
		return doFinal();
	}
	void update(const yzrilyzr_array::ByteArray & input){
		update(input, 0, input.length);
	}
	void update(const yzrilyzr_array::ByteArray & input, u_index offset, u_index length)override{
		buffer.write(input, offset, length);
		int blockSize=getBlockSize();
		if(buffer.available() >= blockSize){
			yzrilyzr_array::ByteArray block(blockSize);
			while(buffer.available() >= blockSize){
				buffer.read(block);
				processBlock(block);
			}
			buffer.compact();
		}
	}
	yzrilyzr_array::ByteArray doFinal()override{
		yzrilyzr_array::ByteArray output=processFinalBlock(buffer.toArray());
		reset();
		return output;
	}
	void reset()override{
		buffer.reset();
	}
	protected:
	virtual yzrilyzr_array::ByteArray processFinalBlock(const yzrilyzr_array::ByteArray & incompleteBlock)=0;
	virtual void processBlock(const yzrilyzr_array::ByteArray & block)=0;
	};
}